#include "jarvis.h"

Jarvis::Jarvis(Grupo g):ConvexHull(g){}

int Jarvis::proximo(int ponto_id, Vector v)
{
//    cout<<"--- proximo INICIO ---------"<<endl;
    int ponto_id_min  = -1;
    double alfa_min = 180.0;// Maior valor possível.
    for (int i=0 ; i<grupo.get_pontos().size() ; i++)
    {
        // Se for o mesmo ponto, teríamos um vetor nulo
        // no cálculo de ângulo entre vetores!
        if (i != ponto_id)
        {
            // Calcular o ângulo entre os vetores (ponto_id ---> i) e v:
            double alfa = anguloGrau(grupo.get_pontos().at(i)-grupo.get_pontos().at(ponto_id),v);
            // Caso este ângulo seja menor do que o selecionado anteriormente:
            //if ((float)alfa < (float)alfa_min)
            if (alfa < alfa_min)
            {
//                cout<<"alfa < alfa_min :: "<<alfa<<" < "<<alfa_min<<endl;
                alfa_min = alfa;
                ponto_id_min = i;
            }
            //cout<<"angulo("<<i<<") = "<<alfa<<endl;
        }
        // Contar iteração:
        this->iteracoes++;
    }
//    cout<<"ponto_id_min = "<<ponto_id_min<<endl;
//    cout<<"--- proximo FIM ------------"<<endl;
    return(ponto_id_min);
}

Fecho Jarvis::convexhull()
{
    // Iniciar contagem de iterações:
    this->iteracoes = 0;

    // Lista para os IDs dos pontos do fecho:
    QList<int> pontos_ids;

    // Cálculo do ponto de ordenada mí­nima:
    int id_menor_y = 0;
    for (int i=1 ; i<grupo.get_pontos().size() ; i++)
        if ((grupo.get_pontos().at(i))(1) < (grupo.get_pontos().at(id_menor_y))(1))
            id_menor_y = i;

    // Adicionando ponto de ordenada mí­nima ao fecho:
    pontos_ids.append(id_menor_y);
    //cout<<"id_menor_y = "<<id_menor_y<<endl;

    // Gerando o próximo ponto e o adicionando ao fecho:
    int ponto_atual = proximo(id_menor_y,Vector("1.0 0.0 0.0"));
    pontos_ids.append(ponto_atual);

    int ponto_anterior = id_menor_y;
    int ponto_proximo = id_menor_y;

    while (true)
    {
        // Calcular o próximo ponto:
        ponto_proximo = proximo(ponto_atual,Vector(grupo.get_pontos().at(ponto_atual)-grupo.get_pontos().at(ponto_anterior)));
        // Checar se chegou ao ponto inicial:
        if (ponto_proximo == id_menor_y) break;
        // Adicionar ao fecho:
        pontos_ids.append(ponto_proximo);
        // Passar ao ponto seguinte:
        ponto_anterior = ponto_atual;
        ponto_atual = ponto_proximo;
        // Contar iteração:
        this->iteracoes++;

        // Checar o limite máximo de iterações foi ultrapassado:
        if (contagemIteracoes().first > contagemIteracoes().second)
        {
            cout<<"AVISO: número máximo de iterações foi ultrapassado!"<<endl;
            break;
        }
    }

    return(Fecho(grupo.get_nome(),pontos_ids));
}
